package com.wei.czz.framework.blog.manager;

import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.dto.blog.audit.groupUser.BlogAuditGroupUserListDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.dict.DictEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.po.blog.audit.groupUser.BlogAuditGroupUserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.CopyUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.utils.TimeUtils;
import com.wei.czz.common.vo.blog.audit.groupUser.BlogAuditGroupUserFormVo;
import com.wei.czz.common.vo.blog.audit.groupUser.BlogAuditGroupUserVo;
import com.wei.czz.common.vo.common.UpdateStatusVo;
import com.wei.czz.framework.blog.entity.BlogAuditGroupUserEntity;
import com.wei.czz.framework.blog.entity.BlogAuditUserConfigEntity;
import com.wei.czz.framework.blog.service.BlogAuditGroupUserService;
import com.wei.czz.framework.blog.service.BlogAuditUserConfigService;
import com.wei.czz.framework.common.entity.DictEntity;
import com.wei.czz.framework.common.wrapper.DictWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2025-01-17 10:17:19
 * className: BlogAuditGroupUserManager
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class BlogAuditGroupUserManager {

    private static final Logger log = LoggerFactory.getLogger(BlogAuditGroupUserManager.class);

    private final BlogAuditGroupUserService blogAuditGroupUserService;

    private final BlogAuditUserConfigService blogAuditUserConfigService;

    private final RedissonClient redissonClient;

    private final DictWrapper dictWrapper;

    @Transactional
    public void saveBlogAuditGroupUser(BlogAuditGroupUserVo vo) {
        // 获取请求用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        Long groupId = vo.getGroupId();
        List<Long> groupIdList = Collections.singletonList(groupId);
        List<Long> userIdList = vo.getUserIdList();

        /*
            获取博客审核分组用户
         */
        List<BlogAuditGroupUserEntity> blogAuditGroupUserList = blogAuditGroupUserService.findList(groupIdList);
        // 收集用户主键
        Set<Long> userIdSet = new HashSet<>();
        // 最大排序等级
        int maxSort = 1;
        for (BlogAuditGroupUserEntity blogAuditGroupUser : blogAuditGroupUserList) {
            userIdSet.add(blogAuditGroupUser.getUserId());

            maxSort = Math.max(maxSort, blogAuditGroupUser.getSort());
        }

        /*
            获取博客审核用户配置
         */
        List<BlogAuditUserConfigEntity> blogAuditUserConfigList = blogAuditUserConfigService.findList(userIdList);
        // 收集用户主键
        Set<Long> configUserIdSet = CopyUtils.mapSet(blogAuditUserConfigList, BlogAuditUserConfigEntity::getUserId);

        /*
            获取博客审核kpi配置
         */
        DictEntity dict = dictWrapper.getOneDict(DictEnum.BLOG_AUDIT_KPI);

        int kpi;
        try {
            kpi = Integer.parseInt(dict.getValue());
        } catch (NumberFormatException e) {
            log.info("博客审核kpi配置值错误");
            throw new CzzException("博客审核kpi配置值错误, 请联系管理员");
        }
        Date kpiDate = TimeUtils.getMonthStartDate(date);

        List<BlogAuditGroupUserEntity> saveBlogAuditGroupUserList = new ArrayList<>();
        List<BlogAuditUserConfigEntity> saveBlogAuditUserConfigList = new ArrayList<>();
        for (Long userId : userIdList) {
            if (userIdSet.contains(userId)) {
                continue;
            }
            // 排序等级自增
            maxSort += 1;

            BlogAuditGroupUserEntity blogAuditGroupUser = new BlogAuditGroupUserEntity();
            blogAuditGroupUser.setGroupId(groupId)
                    .setUserId(userId)
                    .setStatus(CommonEnum.ZERO.getValue())
                    .setSort(maxSort)
                    .setDeleteStatus(CommonEnum.ZERO.getValue())
                    .setUpdateTime(date)
                    .setUpdateUser(StringUtils.EMPTY)
                    .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                    .setCreateTime(date)
                    .setCreateUser(userPo.getUsername())
                    .setCreateUserId(userPo.getUserId());
            saveBlogAuditGroupUserList.add(blogAuditGroupUser);

            if (configUserIdSet.contains(userId)) {
                continue;
            }

            BlogAuditUserConfigEntity blogAuditUserConfig = new BlogAuditUserConfigEntity();
            blogAuditUserConfig.setUserId(userId)
                    .setKpi(kpi)
                    .setKpiDate(kpiDate)
                    .setAuditNum(CommonEnum.ZERO.getValue())
                    .setClaimNum(CommonEnum.ZERO.getValue())
                    .setAutoClaimStatus(CommonEnum.ZERO.getValue())
                    .setAutoClaimTime(date)
                    .setDeleteStatus(CommonEnum.ZERO.getValue())
                    .setUpdateTime(date)
                    .setUpdateUser(StringUtils.EMPTY)
                    .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                    .setCreateTime(date)
                    .setCreateUser(userPo.getUsername())
                    .setCreateUserId(userPo.getUserId());
            saveBlogAuditUserConfigList.add(blogAuditUserConfig);
        }
        if (saveBlogAuditGroupUserList.isEmpty()) {
            log.info("博客审核分组已关联参数里的用户");
            throw new CzzException("已关联所有用户，请勿重复添加");
        }

        /*
            批量保存博客审核分组用户
         */
        blogAuditGroupUserService.batchSave(saveBlogAuditGroupUserList);

        /*
            批量保存博客审核用户配置
         */
        if (!saveBlogAuditUserConfigList.isEmpty()) {
            blogAuditUserConfigService.batchSave(saveBlogAuditUserConfigList);
        }
    }

    public PageDto<BlogAuditGroupUserListDto> getBlogAuditGroupUserPageList(BlogAuditGroupUserFormVo formVo) {

        /*
            分页获取博客审核分组用户
         */
        PageDto<BlogAuditGroupUserPo> pageDto = blogAuditGroupUserService.getPageList(formVo);
        if (pageDto.isEmpty()) {
            return pageDto.rebuild();
        }

        List<BlogAuditGroupUserPo> blogAuditGroupUserPoList = pageDto.getList();

        Function<BlogAuditGroupUserPo, BlogAuditGroupUserListDto> function = blogAuditGroupUserPo -> {
            // 对象映射
            BlogAuditGroupUserListDto blogAuditGroupUserListDto = CopyUtils.map(blogAuditGroupUserPo, BlogAuditGroupUserListDto.class);
            blogAuditGroupUserListDto.setStatusName(CommonEnum.getStatusName(blogAuditGroupUserPo.getStatus()))
                    .setAutoClaimStatusName(Objects.equals(0, blogAuditGroupUserPo.getAutoClaimStatus()) ? "开启" : "关闭");
            return blogAuditGroupUserListDto;
        };
        // 列表映射
        List<BlogAuditGroupUserListDto> blogAuditGroupUserList = CopyUtils.mapList(blogAuditGroupUserPoList, function);
        // 封装返回
        return pageDto.rebuild(blogAuditGroupUserList);
    }

    public void updateBlogAuditGroupUserStatus(UpdateStatusVo updateStatusVo) {
        // 获取请求用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        List<Long> idList = updateStatusVo.getIdList();
        Integer status = updateStatusVo.getStatus();

        Function<Long, BlogAuditGroupUserEntity> function = id -> {
            BlogAuditGroupUserEntity blogAuditGroupUser = new BlogAuditGroupUserEntity();
            blogAuditGroupUser.setId(id)
                    .setStatus(status)
                    .setUpdateTime(date)
                    .setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());
            return blogAuditGroupUser;
        };
        List<BlogAuditGroupUserEntity> updateBlogAuditGroupUserList = CopyUtils.mapList(idList, function);

        /*
            批量修改博客审核分组用户
         */
        blogAuditGroupUserService.batchUpdate(updateBlogAuditGroupUserList);
    }

    public void updateBlogAuditUserAutoClaimStatus(UpdateStatusVo updateStatusVo) {
        // 获取请求用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        List<Long> idList = updateStatusVo.getIdList();
        Integer status = updateStatusVo.getStatus();

        Function<Long, BlogAuditUserConfigEntity> function = id -> {
            BlogAuditUserConfigEntity blogAuditUserConfig = new BlogAuditUserConfigEntity();
            blogAuditUserConfig.setId(id)
                    .setAutoClaimStatus(status)
                    .setAutoClaimTime(date)
                    .setUpdateTime(date)
                    .setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());
            return blogAuditUserConfig;
        };
        List<BlogAuditUserConfigEntity> updateBlogAuditUserConfigList = CopyUtils.mapList(idList, function);

        /*
            批量修改博客审核用户配置
         */
        blogAuditUserConfigService.batchUpdate(updateBlogAuditUserConfigList);

    }

    public void shuffleBlogAuditGroupUser(Long groupId) {
        // 获取请求用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        String lockKey = RedisConstant.LOCK + EntityConstant.BLOG_AUDIT;
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();

        try {
            /*
                获取博客审核分组用户
             */
            List<BlogAuditGroupUserEntity> blogAuditGroupUserList = blogAuditGroupUserService.findList(
                    Collections.singletonList(groupId)
            );
            if (CollectionUtils.isEmpty(blogAuditGroupUserList)) {
                log.info("博客审核分组用户为空，无需打乱");
                return;
            }

            // 打乱列表
            Collections.shuffle(blogAuditGroupUserList);

            // 最新排序等级
            int[] sort = { 1 };

            // 列表映射
            Function<BlogAuditGroupUserEntity, BlogAuditGroupUserEntity> function = blogAuditGroupUser -> {
                BlogAuditGroupUserEntity updateBlogAuditGroupUser = new BlogAuditGroupUserEntity();
                updateBlogAuditGroupUser.setId(blogAuditGroupUser.getId())
                        .setSort(sort[0]++)
                        .setUpdateTime(date)
                        .setUpdateUser(userPo.getUsername())
                        .setUpdateUserId(userPo.getUserId());
                return updateBlogAuditGroupUser;
            };
            List<BlogAuditGroupUserEntity> updateBlogAuditGroupUserList = CopyUtils.mapList(blogAuditGroupUserList, function);

            /*
                批量修改博客审核分组用户
             */
            blogAuditGroupUserService.batchUpdate(updateBlogAuditGroupUserList);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public void deleteBlogAuditGroupUser(List<Long> idList) {
        // 获取请求用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        // 加锁
        String lockKey = RedisConstant.LOCK + EntityConstant.BLOG_AUDIT;
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();

        try {
            // 列表映射
            Function<Long, BlogAuditGroupUserEntity> function = id -> {
                BlogAuditGroupUserEntity updateBlogAuditGroupUser = new BlogAuditGroupUserEntity();
                updateBlogAuditGroupUser.setId(id)
                        .setDeleteStatus(CommonEnum.ONE.getValue())
                        .setUpdateTime(date)
                        .setUpdateUser(userPo.getUsername())
                        .setUpdateUserId(userPo.getUserId());
                return updateBlogAuditGroupUser;
            };
            List<BlogAuditGroupUserEntity> updateBlogAuditGroupUserList = CopyUtils.mapList(idList, function);

            /*
                批量删除博客审核分组用户
             */
            blogAuditGroupUserService.batchUpdate(updateBlogAuditGroupUserList);

        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}
